package com.yuan.springcloud.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yuan.springcloud.common.exception.ServiceException;
import com.yuan.springcloud.user.bean.dto.UserInfoDTO;
import com.yuan.springcloud.user.bean.dto.UserSignDTO;
import com.yuan.springcloud.user.bean.po.UserPO;
import com.yuan.springcloud.user.bean.po.UserSignPO;
import com.yuan.springcloud.user.bean.vo.UserQueryVO;
import com.yuan.springcloud.user.bean.vo.UserSignVO;
import com.yuan.springcloud.user.bean.vo.UserVO;
import com.yuan.springcloud.user.constant.RedisCacheKey;
import com.yuan.springcloud.user.dao.UserDAO;
import com.yuan.springcloud.user.dao.UserSignDAO;
import com.yuan.springcloud.user.service.UserService;
import com.yuan.springcloud.user.utils.Transform;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBitSet;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;

/**
 * @author YouYuan
 * @date 2020/8/16 23:59
 */
@Slf4j
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDAO userDAO;
    @Autowired
    private UserSignDAO userSignDAO;

    @Autowired
    private Transform transform;

    @Autowired
    private RedissonClient redissonClient;

    @Override
    public List<UserPO> queryAllUserList() {
        return userDAO.selectList(new QueryWrapper<UserPO>().eq("username", "YouYuan"));
    }

    @Override
    public int update(UserVO user) {
        if (user == null) {
            return 0;
        }
        return userDAO.updateById(transform.user.vo2po(user));
    }

    @Override
    public List<UserPO> queryUserListById(List<Integer> userIdList) {
        return userDAO.queryUserListById(userIdList);
    }

    @Override
    public IPage<UserPO> queryUserList(Page<?> page) {
        return userDAO.queryUserList(page);
    }

    @Override
    public List<UserPO> queryUserList(UserQueryVO queryParam) {
        return userDAO.queryUserList(queryParam);
    }

    @Override
    public int queryUserCount() {
        return userDAO.queryUserCount();
    }

    @Override
    public List<UserInfoDTO> queryUserInfoList() {
        return userDAO.queryUserInfoList();
    }

    @Override
    public int login(Long userId) {
        RBitSet bitSet = redissonClient.getBitSet(RedisCacheKey.USER_LOGIN_STATUS);
        bitSet.set(userId, true);
        log.info("user:{} login", userId);
        return 1;
    }


    @Override
    public int logout(Long userId) {
        RBitSet bitSet = redissonClient.getBitSet(RedisCacheKey.USER_LOGIN_STATUS);
        boolean isLogin = bitSet.get(userId);
        if (isLogin) {
            // 设置用户登录位为false
            bitSet.set(userId, false);
            log.info("user:{} logout", userId);
        } else {
            throw new ServiceException("用户未登录", "1");
        }
        return 1;
    }

    @Override
    public List<Integer> queryOnlineList() {
        List<Integer> userList = new LinkedList<>();
        for (int i = 1; i <= 10000; i++) {
            userList.add(i);//模拟数据库查询出来的用户列表
        }
        RBitSet bitSet = redissonClient.getBitSet(RedisCacheKey.USER_LOGIN_STATUS);
        BitSet userLoginBit = bitSet.asBitSet();
        Iterator<Integer> iterator = userList.iterator();
        while (iterator.hasNext()) {
            boolean isLogin = userLoginBit.get(iterator.next());
            if (!isLogin) {
                // 如果用户不在线，则剔除
                iterator.remove();
            }
        }
        return userList;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Integer sign(UserSignVO userSignVO) {
        UserSignPO userSignPO = Transform.userSign.vo2po(userSignVO);
        Date now = new Date();
        userSignPO.setSignDate(now);
        userSignPO.setUpdateTime(now);
        QueryWrapper<UserSignPO> query = new QueryWrapper<>();
        query.eq("user_id", userSignPO.userId);
        Long id = userSignDAO.queryIdByUserId(userSignPO.getUserId());
        int rs = 0;
        if (id != null) {
            userSignPO.setId(id);
            rs = userSignDAO.updateById(userSignPO);
        } else {
            userSignPO.setCreateTime(now);
            rs = userSignDAO.insert(userSignPO);
        }
//        int rs = userSignDAO.insertOrUpdate(userSignPO);
        return rs;
    }
}
